#include "Follows.h"

Follows::Follows(){
	this->followsIndex = vector<pair<int, int>>();
	this->followsChainIndex = vector<vector<int>>();
}

int Follows::addFollows(int stmtNum1, int stmtNum2){
	if(stmtNum1 <= 0 || stmtNum2 <= 0){
		return -1;
	}
	this->followsIndex.push_back(make_pair(stmtNum1, stmtNum2));
	bool newChain = true;
	for(vector<vector<int>>::iterator it = followsChainIndex.begin(); it != followsChainIndex.end(); it++) {
		if(it->back() == stmtNum1){
			newChain = false;
			it->push_back(stmtNum2);
			break;
		}
	}
	if (newChain){
		vector<int> newC = vector<int>();
		newC.push_back(stmtNum1);
		newC.push_back(stmtNum2);
		this->followsChainIndex.push_back(newC);
	}
	return followsIndex.size()-1;
}

vector<pair<int, int>> Follows::getFollows(int stmtNum1, int stmtNum2){
	set<pair<int, int>>* matchingPairs = new set<pair<int, int>>();
	for(vector<pair<int, int>>::iterator it = followsIndex.begin(); it != followsIndex.end(); it++) {
		if((it->first == stmtNum1 || stmtNum1 == ANYVALUE) && 
			(it->second == stmtNum2 || stmtNum2 == ANYVALUE)){
				matchingPairs->insert(*it);
		}
	}
	return vector<pair<int, int>>(matchingPairs->begin(), matchingPairs->end());
}

vector<pair<int, int>> Follows::getFollowsStar(int stmtNum1, int stmtNum2){
	set<pair<int, int>>* result = new set<pair<int, int>>();
	if(stmtNum1 == ANYVALUE && stmtNum2 == ANYVALUE){
		for(vector<vector<int>>::iterator itX = followsChainIndex.begin(); itX != followsChainIndex.end(); itX++){
			buildMeshPairs(*result, *itX);
		}
		return vector<pair<int, int>>(result->begin(), result->end());
	}
	vector<int> matchingStmtNums = vector<int>();
	bool foundStmtNum1 = false, foundStmtNum2 = false;
	vector<vector<int>>::iterator it1;
	vector<vector<int>>::iterator it2;
	for(vector<vector<int>>::iterator itX = followsChainIndex.begin(); itX != followsChainIndex.end(); itX++) {
		for(vector<int>::iterator itY = itX->begin(); itY != itX->end(); itY++){
			if (*itY == stmtNum1){
				it1 = itX;
				foundStmtNum1 = true;
			}
			if (*itY == stmtNum2){
				it2 = itX;
				foundStmtNum2 = true;
			}
		}
	}
	if (stmtNum1 != ANYVALUE && stmtNum2 != ANYVALUE){
		if (foundStmtNum1 && foundStmtNum2){
			if (it1->at(0) == it2->at(0) && stmtNum1 < stmtNum2){
				result->insert(make_pair(stmtNum1, stmtNum2));
			}
		}
	}else if(stmtNum1 != ANYVALUE && foundStmtNum1){
		vector<int>::iterator it = it1->begin();
		while(*it != stmtNum1){
			it++;
		}
		matchingStmtNums.insert(matchingStmtNums.begin(), it, it1->end());
		buildPairs(*result, matchingStmtNums, FIXFIRST);
	}else if(stmtNum2 != ANYVALUE && foundStmtNum2){
		vector<int>::iterator it = it2->begin();
		while(*it != stmtNum2){
			it++;
		}
		matchingStmtNums.insert(matchingStmtNums.begin(), it2->begin(), ++it);
		buildPairs(*result, matchingStmtNums, FIXLAST);
	}
	return vector<pair<int, int>>(result->begin(), result->end());
}

void Follows::buildPairs(set<pair<int, int>> &result, vector<int> input, int fixFirstOrLast){
	if (fixFirstOrLast == FIXFIRST){
		int first = input.front();
		input.erase(input.begin());
		for (vector<int>::iterator it = input.begin(); it != input.end(); it++){
			result.insert(make_pair(first, *it));
		}
	}else if (fixFirstOrLast == FIXLAST){
		int last = input.back();
		input.erase(input.end()-1);
		for (vector<int>::iterator it = input.begin(); it != input.end(); it++){
			result.insert(make_pair(*it, last));
		}
	}
}

void Follows::buildMeshPairs(set<pair<int, int>> &result, vector<int> input){
	for (vector<int>::iterator itX = input.begin(); itX != input.end()-1; itX++){
		for (vector<int>::iterator itY = itX+1; itY != input.end(); itY++){
			result.insert(make_pair(*itX, *itY));
		}
	}
}